package com.lemon.exam.common.util;

import com.alibaba.fastjson2.JSON;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.teautil.models.RuntimeOptions;
import com.lemon.exam.common.enums.SmsEnum;
import com.lemon.exam.common.properties.AliyunProperties;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 短信工具类
 *
 * @author Lemon
 * @since 2025/4/9 19:48
 */
@Slf4j
@Component
public class SmsUtil {
    @Resource
    private AliyunProperties aliyunProperties;

    @Autowired
    @Qualifier("smsScheduler")
    private Scheduler smsScheduler;

    /**
     * 发送短信
     *
     * @param phone
     * @param params
     * @param smsEnum
     * @return
     */
    private CompletableFuture<Boolean> asyncSend(String phone, Map<String, String> params, SmsEnum smsEnum) {
        //1.短信请求
        var request = new SendSmsRequest()
                .setPhoneNumbers(phone)
                .setSignName(aliyunProperties.getSms().getSignName())
                .setTemplateCode(smsEnum.getCode())
                .setTemplateParam(JSON.toJSONString(params));

        //2.异步发送短信
        return CompletableFuture.supplyAsync(() -> {
            try {
                var response = aliyunProperties.getSms().client().sendSmsWithOptions(request, new RuntimeOptions());
                log.info("短信发送结果：{}", response.getBody().toString());
                return "OK".equals(response.getBody().getCode());
            } catch (Exception e) {
                log.error("短信发送失败：{}", e.getMessage());
                return false;
            }
        });
    }

    /**
     * 发送短信
     *
     * @param phone   手机号
     * @param params  模板参数信息
     * @param smsEnum 短信模板类型
     * @return
     */
    public Mono<Boolean> send(String phone, Map<String, String> params, SmsEnum smsEnum) {
        return Mono.fromFuture(() -> asyncSend(phone, params, smsEnum)).subscribeOn(smsScheduler);
    }
}
